Skip to content

feat(suite): add declarative backend suite sync#269

Closed
cmdr-chara wants to merge 2 commits into
TestSprite:mainfrom
cmdr-chara:feat/suitefile-mvp
Closed

feat(suite): add declarative backend suite sync#269
cmdr-chara wants to merge 2 commits into
TestSprite:mainfrom
cmdr-chara:feat/suitefile-mvp

Conversation

@cmdr-chara

@cmdr-chara cmdr-chara commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Adds a declarative, backend-only Suitefile workflow for keeping a repository-owned test suite aligned with a TestSprite project.

  • suite validate strictly validates the manifest, referenced Python sources, and dependency graph without credentials or network access.
  • suite graph compiles produces/consumes declarations into deterministic execution waves, with teardown/cleanup tests placed last.
  • suite plan compares declared metadata and code with remote tests and classifies each entry as create, update, unchanged, or conflict.
  • suite apply --confirm performs guarded creates and updates. It never deletes unmanaged remote tests.
  • An adjacent atomic lockfile preserves suite-key identity, code versions, desired-state hashes, and pending create idempotency across interrupted applies.

Validation fails closed on unknown fields, duplicate identities, missing or ambiguous producers, self-dependencies, cycles, oversized code, lexical path escapes, and symlink escapes. Remote tests are adopted only through an explicit testId or lockfile identity; a same-name test is treated as a conflict.

This is complementary to #125 / PR #265: export/import round-trips one test definition, while Suitefiles compile and reconcile a multi-test dependency graph.

Related issue

Closes #268

Type of change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that changes existing behavior)
  • Documentation only
  • Build / CI / chore

Checklist

  • PR targets the main branch.
  • Commits follow Conventional Commits.
  • npm run lint and npm run format:check pass.
  • npm run typecheck passes.
  • npm test passes and coverage stays at or above the 80% gate.
  • New behavior is covered by unit tests (mock-based; no network or credentials required).
  • No secrets, API keys, internal endpoints, or personal data are included.
  • User-facing changes are reflected in README.md / DOCUMENTATION.md.

Notes for reviewers

  • Full unit run: 2,016 passed, 4 platform/existing skips.
  • Coverage passed: 85.64% lines/statements, 90.16% functions, 83.8% branches.
  • Build and npm pack --dry-run pass; the tarball includes dist/commands/suite.js and its declarations.
  • npm run test:e2e was attempted on Windows. Eight assertions fail in four pre-existing, untouched suites: slash-normalized agent paths, Windows child-process signal exit codes, and the skill-nudge fixture. The Suitefile change does not touch those paths.
  • The symlink-escape fixture is skipped on Windows because creating file symlinks requires platform privileges; Linux CI exercises it. The runtime guard is platform-independent.
  • Remote reconciliation is covered with mocked API integration tests. No live TestSprite tenant was mutated during development.
  • Schema v1 intentionally excludes frontend tests and deletion. priority and category are modified only when declared; produces and consumes are authoritative, with omission meaning an empty list.

Summary by CodeRabbit

  • New Features

    • Added declarative backend suite management via suite validate, suite graph, suite plan, and suite apply.
    • Supports deterministic dependency-wave graphs, offline --dry-run planning with drift detection, and guarded reconciliation of test metadata/code with lockfile-backed state.
    • Enforces --confirm for mutations and adds conflict handling, safe resume of interrupted creates, and refusal on unsafe manifest/code paths.
  • Documentation

    • Updated README and DOCUMENTATION with Suite command reference, Suitefile/lockfile schema and behavior, and clarified --dry-run execution guarantees.
  • Tests

    • Added end-to-end Suite command coverage plus help snapshot updates.

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 736dcbcb-6c69-47e6-b675-fbc73ad0b5a9

📥 Commits

Reviewing files that changed from the base of the PR and between 51d7c47 and 7cb64a6.

📒 Files selected for processing (3)
  • src/commands/suite.test.ts
  • src/commands/suite.ts
  • src/lib/http.ts

Walkthrough

Adds a declarative backend Suitefile workflow with local validation and graph compilation, remote drift planning, confirmed idempotent apply operations, atomic lockfiles, CLI registration, tests, and documentation.

Changes

Declarative backend suite management

Layer / File(s) Summary
Manifest validation and dependency graph
src/commands/suite.ts, src/commands/suite.test.ts, DOCUMENTATION.md
Validates Suitefile schemas and referenced Python files, enforces path and size safety, and compiles deterministic dependency waves with cycle and producer checks.
Remote reconciliation planning
src/commands/suite.ts, src/commands/suite.test.ts
Compares locked Suitefile definitions with remote metadata and code, classifying creates, updates, unchanged tests, conflicts, and unmanaged tests.
Confirmed mutation and lock persistence
src/commands/suite.ts, src/commands/suite.test.ts, src/lib/http.ts
Applies confirmed non-conflicting changes with idempotency keys and atomically records completed or pending operations in the lockfile.
CLI registration and documentation
src/index.ts, test/help.snapshot.test.ts, README.md, CHANGELOG.md, DOCUMENTATION.md
Registers suite commands, updates help coverage, and documents command behavior, dry-run handling, and safety rules.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Developer
  participant SuiteCLI
  participant Suitefile
  participant BackendAPI
  participant SuiteLockfile
  Developer->>SuiteCLI: suite plan or suite apply
  SuiteCLI->>Suitefile: validate manifest and compile graph
  SuiteCLI->>BackendAPI: fetch remote tests and code
  BackendAPI-->>SuiteCLI: remote state
  SuiteCLI->>SuiteCLI: calculate drift and conflicts
  SuiteCLI->>BackendAPI: confirmed idempotent mutations
  BackendAPI-->>SuiteCLI: mutation results
  SuiteCLI->>SuiteLockfile: atomically persist suite identity and hashes
Loading

Suggested reviewers: ruili-testsprite, zeshi-du

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.44% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: adding declarative suite sync commands and workflow.
Linked Issues check ✅ Passed The changes implement the Suitefile workflow, four CLI commands, safety rules, docs, tests, and lockfile behavior requested by #268.
Out of Scope Changes check ✅ Passed The diff stays focused on the suite feature and related docs/tests; no clearly unrelated changes are present.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install timed out. The project may have too many dependencies for the sandbox.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/commands/suite.test.ts (1)

294-455: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider covering the apply-refuses-conflicts error path.

The apply tests exercise create/update/confirm-gating/pending-resume, but not runSuiteApply's rejection when the plan contains a conflict (suite.ts Line 408-414) — a core safety guarantee ("refuses any plan containing conflicts"). A small test asserting the VALIDATION_ERROR with the conflict(s) message would lock in that contract.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/commands/suite.test.ts` around lines 294 - 455, Add a focused test in the
“suite apply” describe block that makes runSuitePlan produce a conflict, then
invokes runSuiteApply and asserts it rejects with code VALIDATION_ERROR and a
message mentioning conflicts. Keep the test focused on the safety behavior that
apply refuses any plan containing conflicts, without performing remote
mutations.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/commands/suite.ts`:
- Around line 430-441: Update the item.action === 'noop' branch to preserve the
existing lock.entries[item.key] when its testId, codeVersion, and desiredHash
already match the incoming item. Only call makeCompletedLockEntry when those
meaningful fields differ or no existing entry is available, avoiding an
updatedAt refresh for unchanged entries.
- Around line 831-841: Update resolveRemoteCode to enforce the client’s
requestTimeoutMs deadline for HTTPS downloads, using the existing shared
timeout/abort mechanism rather than an unbounded fetch. Pass the abort signal
through the selected fetch implementation and route timeout or transport
failures through the shared error-classification path, while preserving the
current HTTP status validation and response text behavior.

---

Nitpick comments:
In `@src/commands/suite.test.ts`:
- Around line 294-455: Add a focused test in the “suite apply” describe block
that makes runSuitePlan produce a conflict, then invokes runSuiteApply and
asserts it rejects with code VALIDATION_ERROR and a message mentioning
conflicts. Keep the test focused on the safety behavior that apply refuses any
plan containing conflicts, without performing remote mutations.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 01d2fc1c-fc9b-4df7-b2be-b615a1b2abe9

📥 Commits

Reviewing files that changed from the base of the PR and between 2708a40 and 51d7c47.

⛔ Files ignored due to path filters (1)
  • test/__snapshots__/help.snapshot.test.ts.snap is excluded by !**/*.snap, !**/*.snap
📒 Files selected for processing (7)
  • CHANGELOG.md
  • DOCUMENTATION.md
  • README.md
  • src/commands/suite.test.ts
  • src/commands/suite.ts
  • src/index.ts
  • test/help.snapshot.test.ts

Comment thread src/commands/suite.ts
Comment thread src/commands/suite.ts Outdated
@cmdr-chara

Copy link
Copy Markdown
Contributor Author

Addressed all review feedback in 7cb64a6: no-op lockfiles are byte-stable, presigned code downloads honor the configured request timeout, and suite apply now has a regression test proving conflicts produce VALIDATION_ERROR without sending mutations. Verified with format, lint, typecheck, 2,019 passing unit tests, and a production build.

@zeshi-du

Copy link
Copy Markdown
Contributor

Maintainer verdict: declining — not on quality, on architecture ownership. Reviewed in full, and credit where due: this is genuinely well-built (allowlist field validation, lexical + symlink path-escape rejection, never-delete reconcile semantics, idempotent create resume, 15 focused tests — all verified).

Why it can't land: the platform already owns both concepts this rebuilds client-side. Server-side, test lists and a dependency-aware execution planner (topological wave ordering from produce/consume declarations) exist today and are the committed foundation for the CLI's suite surface — the decided direction is expose that server capability through a thin CLI facade, not compile execution plans in the client. A client-side Suitefile compiler would fork the semantics: two wave-planners with drift between them, and a declarative apply loop that lands exactly on the write surface we're required to put server-side quota enforcement in front of first. That work is scheduled internally (suite/testlist CLI surface, quota-first), and this PR would pre-empt its design in the wrong layer.

What carries forward: the demand signal is real and registered — a declarative, version-controllable suite definition with drift detection is precisely the UX we want on top of the server facade, and this PR is a useful reference for that surface's ergonomics (validate/graph/plan/apply --confirm is a good verb set). We've linked it into the internal testlist workstream.

Process note, gently: #268 was self-filed and self-assigned four minutes before this PR, with the code already written — CONTRIBUTING asks for triage before implementation on feature-scale proposals, exactly so 2,000-line efforts don't land on a direction we can't take. The gate isn't bureaucracy; it's how we avoid wasting work like this. Closing #268 alongside.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: declarative backend Suitefile compiler and drift-safe sync

2 participants